package com.entrogy.controller;

import com.alibaba.fastjson.JSONObject;
import com.entrogy.bean.*;
import com.entrogy.service.*;
import com.entrogy.timing.ChangePersonTimeThread;
import com.entrogy.utils.SendUtils;
import com.entrogy.utils.THDio;
import com.entrogy.utils.constants.Constants;
import com.entrogy.utils.constants.ErrorEnum;
import com.github.pagehelper.PageHelper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @ClassName MeetingRoomController
 * @Description
 * @Author luoxingjiang
 * @Date 2019/8/6 0006 下午 3:43
 * @Version 1.0
 **/
@RestController
@RequestMapping(value = "/meetingRoom")
@Api(description = "会议室管理接口")
public class MeetingRoomController {

    private static final Logger logger = LoggerFactory.getLogger(MeetingRoomController.class);

    @Autowired
    private UserService userService;

    @Autowired
    private MeetingRoomService meetingRoomService;

    @Autowired
    private MessageService messageService;

    @Autowired
    private SchoolService schoolService;

    @Autowired
    private PermissionService permissionService;

    @Value("${show.image.url}")
    private String showImage;

    @GetMapping(value = "/list")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "meetingRoomName", value = "会议室名字", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "userId", value = "用户id", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "selectDate", value = "选择的日期", dataType = "date", paramType = "query"),
    })
    @ApiOperation(value = "查询会议室列表以及当天的使用情况")
    public Msg getMeetingRoomList(String meetingRoomName, String userId, String selectDate){
        Integer schoolCode = userService.getSchoolCodeByUserId(userId);
        List<MeetingRoomEntity> meetingRoomList = meetingRoomService.listMeetingRoom(meetingRoomName, schoolCode, selectDate, null);
        return Msg.success().add("meetingRoomList", meetingRoomList).add("showImage", showImage);
    }

    @PostMapping(value = "/insertMeetingApplyRecord")
    @ApiOperation(value = "申请会议室使用")
    public Msg insertMeetingApplyRecord(@RequestBody MeetingApplyRecordEntity meetingApplyRecordEntity){
        Date data = new Date();
        String current = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(data);
        // 申请时需要校验是否在该时间段已经有其他人已经申请了
        Integer meetingRoomId = meetingApplyRecordEntity.getMeetingRoomId();
        String applyUserId = meetingApplyRecordEntity.getApplyUserId();
        Integer schoolCode = userService.getSchoolCodeByUserId(applyUserId);
        String applyDate = new SimpleDateFormat("yyyy-MM-dd").format(meetingApplyRecordEntity.getApplyDate());
        List<MeetingRoomEntity> meetingRoomList = meetingRoomService.listMeetingRoom(null, schoolCode, applyDate, meetingRoomId);
        String startTime = meetingApplyRecordEntity.getStartTime();
        String endTime = meetingApplyRecordEntity.getEndTime();
        if (meetingRoomList.size() == 1){
            List<JSONObject> disableTimeList = meetingRoomList.get(0).getDisableTime();
            for (JSONObject disableTime : disableTimeList) {
                String disableStartTime = disableTime.getString("startTime");
                String disableEndTime = disableTime.getString("endTime");
                // 禁用时间段和当前人员申请的时间段的关系是两个区间的关系，自己画图去
                if ((disableEndTime.compareTo(startTime) > 0 && startTime.compareTo(disableStartTime) > 0)
                        || (disableStartTime.compareTo(endTime) < 0 && disableEndTime.compareTo(endTime) > 0)
                        || (disableStartTime.compareTo(startTime) >= 0 && disableEndTime.compareTo(endTime) <= 0)
                        || (disableStartTime).compareTo(startTime) < 0 && disableEndTime.compareTo(endTime) > 0){
                    return Msg.fail(ErrorEnum.E_101, "对不起，当前申请的时间段和该会议室已被申请的时间段重合，请重新选择时间！");
                }
            }
        }
        // 比较申请的时间是否在当前时间之前
        String currentDate = current.substring(0,10);
        String currentTime = current.substring(11);
        if (currentDate.compareTo(applyDate) > 0 && currentTime.compareTo(startTime) > 0){
            return Msg.fail(ErrorEnum.E_101, "对不起，您不能申请当前时间之前的时间段，请重新选择时间！");
        }

        // 判断该会议室是否需要审核
        boolean requireAudit = meetingRoomService.isRequireAudit(meetingApplyRecordEntity.getMeetingRoomId());
        boolean result;
        // audit字段表示审核是否通过，1为待审核，2为审核通过，3审核不通过，如果不需要审核
        if (!requireAudit){
            // 如果申请的会议室是不用审核的话，那么直接在申请表里插入一条审核通过的数据，然后通知开会人员即可
            meetingApplyRecordEntity.setAudited(2);
            result = meetingRoomService.insertMeetingApplyRecord(meetingApplyRecordEntity);
            Integer meetingRoomApplyId = meetingApplyRecordEntity.getId();
            List<String> phoneList = meetingRoomService.listMeetingPersonPhone(meetingRoomApplyId);
            for (String phone : phoneList) {
                MeetingApplyRecordEntity meetingDetail = meetingRoomService.getApplyDetail(meetingRoomApplyId);
                String content = new SimpleDateFormat("yyyy年MM月dd日").format(meetingDetail.getApplyDate()) + " " + meetingDetail.getStartTime() +
                        "于" + meetingDetail.getMeetingRoomName() + "召开《" + meetingDetail.getMeetingTitle() + "》,请准时参加，";
                sendToMeetingPerson(phone, "200643", content);
            }
            // 短信通知完成后，还需要将这些参会人员的人脸数据推送到会议室人脸识别设备
            pushMeetingPersonToDevice(meetingApplyRecordEntity);
        }else {
            meetingApplyRecordEntity.setAudited(1);
            result = meetingRoomService.insertMeetingApplyRecord(meetingApplyRecordEntity);
            // 数据插入完成后，给相应的管理员发送公众消息
            // 查询申请会议室的管理员的电话号码
            String phone = meetingRoomService.getMeetingRoomAdminPhone(meetingApplyRecordEntity.getMeetingRoomId());
            PubCountEntity pubCountEntity = messageService.getPubCountOpenidByPhone(phone);
            String content = "您所管理的会议室《" + meetingApplyRecordEntity.getMeetingRoomName() + "》有新的申请记录，请及时处理！";
            String schoolName = schoolService.getSchoolName(schoolCode);
            sendWeiXinMessage(pubCountEntity, content, schoolName, "packageA/pages/meeting/meetinglist?type=2");
        }
        if (result)
            return Msg.success();
        return Msg.fail(ErrorEnum.E_101, "申请会议数据插入失败！");
    }


    @GetMapping(value = "/listApply")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "currentPage", value = "当前页数", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "Integer", paramType = "query"),
    })
    @ApiOperation(value = "会议室管理员查看所有申请记录")
    public Msg listApply(String userId, Integer currentPage, Integer pageSize){
        Integer total = meetingRoomService.countMeetingApplyRecord(userId);
        PageHelper.startPage(currentPage, pageSize);
        List<MeetingApplyRecordEntity> meetingApplyRecordList = meetingRoomService.listMeetingApplyRecord(userId);
        return Msg.success().add("meetingApplyRecordList", meetingApplyRecordList).add("total", total);
    }

    @GetMapping(value = "/listAttendanceMeeting")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "currentPage", value = "当前页数", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "Integer", paramType = "query"),
    })
    @ApiOperation(value = "教职员工查看参与的会议")
    public Msg listAttendanceMeeting(String userId, Integer currentPage, Integer pageSize){
        Integer total = meetingRoomService.countAttendanceMeeting(userId);
        PageHelper.startPage(currentPage, pageSize);
        List<MeetingApplyRecordEntity> meetingApplyRecordList = meetingRoomService.listAttendanceMeeting(userId);
        return Msg.success().add("meetingApplyRecordList", meetingApplyRecordList).add("total", total);
    }

    @GetMapping(value = "/listMyApply")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "currentPage", value = "当前页数", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "Integer", paramType = "query"),
    })
    @ApiOperation(value = "教职员工查看申请的会议")
    public Msg listMyApply(String userId, Integer currentPage, Integer pageSize){
        Integer total = meetingRoomService.countMyApply(userId);
        PageHelper.startPage(currentPage, pageSize);
        List<MeetingApplyRecordEntity> meetingApplyRecordList = meetingRoomService.listMyApply(userId);
        return Msg.success().add("meetingApplyRecordList", meetingApplyRecordList).add("total", total);
    }

    @GetMapping(value = "/getApplyDetail")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "meetingRoomApplyId", value = "会议室申请id", dataType = "Integer", paramType = "query"),
    })
    @ApiOperation(value = "查看会议记录详情")
    public Msg getApplyDetail(Integer meetingRoomApplyId){
        MeetingApplyRecordEntity meetingApplyRecordDetail = meetingRoomService.getApplyDetail(meetingRoomApplyId);
        return Msg.success().add("meetingApplyRecordDetail", meetingApplyRecordDetail).add("showImage", showImage);
    }

    @PutMapping(value = "/handleMeetingApply")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "meetingRoomApplyId", value = "会议室申请id", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name = "audited", value = "是否审核通过", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name = "opinion", value = "审核意见", dataType = "String", paramType = "query"),
    })
    @ApiOperation(value = "审核会议室使用申请")
    public Msg handleMeetingApply(String userId, Integer meetingRoomApplyId, Integer audited, String opinion){
        // 审核前需要判断该申请是否已取消
        MeetingApplyRecordEntity meetingApplyRecordEntity = meetingRoomService.getApplyDetail(meetingRoomApplyId);
        if (meetingApplyRecordEntity.getAudited().equals(4)){
            return Msg.fail(ErrorEnum.E_101, "操作失败，该申请已被申请人取消！");
        }
        // 更新该条申请的状态
        boolean result = meetingRoomService.updateMeetingRoomApplyRecord(meetingRoomApplyId, audited, opinion);
        if (result){
            PubCountEntity pubCountEntity = meetingRoomService.getApplyUserOpenId(meetingRoomApplyId);
            String content = null;
            // 状态更新成功后，微信通知申请人
            if (audited.equals(2)){
                content = "您的会议室申请已经通过，并且已经通知相关参会人员，您可以在申请的时间段内进入会议室开会，谢谢！";
            }else if (audited.equals(3)){
                content = "对不起，您的会议室申请被会议室管理员拒绝，拒绝理由为："  + opinion;
            }
            Integer schoolCode = userService.getSchoolCodeByUserId(userId);
            String schoolName = schoolService.getSchoolName(schoolCode);
            sendWeiXinMessage(pubCountEntity, content, schoolName, "packageA/pages/meeting/meetinglist?type=1");
            // 申请人通知完成后，如果审核通过，那么还要短信通知所有开会人员
            if (audited.equals(2)){
                List<String> phoneList = meetingRoomService.listMeetingPersonPhone(meetingRoomApplyId);
                for (String phone : phoneList) {
                    MeetingApplyRecordEntity meetingDetail = meetingRoomService.getApplyDetail(meetingRoomApplyId);
                    content = new SimpleDateFormat("yyyy年MM月dd日").format(meetingDetail.getApplyDate()) + " " + meetingDetail.getStartTime() +
                            "于" + meetingDetail.getMeetingRoomName() + "召开《" + meetingDetail.getMeetingTitle() + "》,请准时参加，";
                    sendToMeetingPerson(phone, "200643", content);
                }
                // 短信通知完成后，还需要将这些参会人员的人脸数据推送到会议室人脸识别设备
                MeetingApplyRecordEntity meetingApplyRecord = meetingRoomService.getApplyDetail(meetingRoomApplyId);
                pushMeetingPersonToDevice(meetingApplyRecord);
            }
        }
        return Msg.success();
    }

    @PutMapping(value = "/cancelMeetingApply")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "meetingRoomApplyId", value = "会议室申请id", dataType = "Integer", paramType = "query", required = true),
    })
    @ApiOperation(value = "取消会议室使用申请")
    public Msg cancelMeetingApply(Integer meetingRoomApplyId){
        //申请状态为4则为取消
        Integer audited = 4;
        MeetingApplyRecordEntity applyDetail = meetingRoomService.getApplyDetail(meetingRoomApplyId);
        if (applyDetail.getAudited().equals(3)){
            return Msg.fail(ErrorEnum.E_101, "对不起，该申请已被拒绝，取消失败");
        }
        //更新该条申请的状态
        boolean result = meetingRoomService.updateMeetingRoomApplyRecord(meetingRoomApplyId, audited, null);
        if (result)
            return Msg.success();
        return Msg.fail(ErrorEnum.E_101, "取消会议室使用申请失败！");
    }

    @GetMapping(value = "/listMeetingRoomSimple")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户id", dataType = "String", paramType = "query", required = true),
    })
    @ApiOperation(value = "查询会议室列表---简单版")
    public Msg getMeetingRoomListSimple(String userId){
        Integer schoolCode = userService.getSchoolCodeByUserId(userId);
        List<JSONObject> meetingRoomList = meetingRoomService.getMeetingRoomListSimple(schoolCode);
        return Msg.success().add("meetingRoomList", meetingRoomList);
    }

    @PostMapping(value = "/insertMeetingRoom")
    @ApiOperation(value = "新增会议室")
    public Msg insertMeetingRoom(@RequestBody MeetingRoomEntity meetingRoom){
        boolean result = meetingRoomService.insertMeetingRoom(meetingRoom);
        if (result)
            return Msg.success();
        return Msg.fail(ErrorEnum.E_101, "新增会议室数据插入失败！");
    }

    @GetMapping(value = "/getMeetingAttendance")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "meetingRoomApplyId", value = "会议室申请id", dataType = "Integer", paramType = "query"),
    })
    @ApiOperation(value = "查看会议签到详情")
    public Msg getMeetingAttendance(Integer meetingRoomApplyId){
        //查询出该会议的开始日期以及开始时间和结束时间
        JSONObject meetingDateDetail = meetingRoomService.getMeetingDate(meetingRoomApplyId);
        //根据会议日期得出存储该天流水记录的表名
        Date meetingDate = meetingDateDetail.getSqlDate("applyDate");
        String tableName = "pass_record" + new SimpleDateFormat("yyyyMMdd").format(meetingDate);
        //开会截止时间，用于查询考勤记录，格式为yyyy-MM-dd HH:mm:ss，此处直接拼接
        String meetingEndTime = new SimpleDateFormat("yyyy-MM-dd").format(meetingDate) + " " + meetingDateDetail.getString("endTime");
        //查询截止至会议结束之前已到人员名单
        List<PersonMeetingAttendanceEntity> personMeetingAttendanceList = meetingRoomService.listAttendancePerson(meetingRoomApplyId, tableName, meetingEndTime);
        //查询所有会议人员名单
        List<PersonMeetingAttendanceEntity> allMeetingPerson = meetingRoomService.listAllMeetingPerson(meetingRoomApplyId);
        //计算会议人员参会状态
        for (PersonMeetingAttendanceEntity personMeetingAttendance : personMeetingAttendanceList) {
            for (PersonMeetingAttendanceEntity meetingPerson : allMeetingPerson) {
                if (meetingPerson.getId().equals(personMeetingAttendance.getId())){
                    meetingPerson.setStatus(1);
                }else {
                    meetingPerson.setStatus(0);
                }
            }
        }
        Integer shouldAttendance = allMeetingPerson.size();
        Integer actualAttendance = personMeetingAttendanceList.size();
        return Msg.success().add("allMeetingPerson", allMeetingPerson).add("shouldAttendance", shouldAttendance).add("actualAttendance", actualAttendance).add("showImage", showImage);
    }

    @PostMapping(value = "/updateMeetingRoom")
    @ApiOperation(value = "修改会议室")
    public Msg updateMeetingRoom(@RequestBody MeetingRoomEntity meetingRoom){
        boolean result = meetingRoomService.updateMeetingRoom(meetingRoom);
        if (result)
            return Msg.success();
        return Msg.fail(ErrorEnum.E_101, "修改会议室失败！");
    }

    @GetMapping(value = "/isManager")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "uid", value = "用户id", dataType = "String", paramType = "query"),
    })
    @ApiOperation(value = "当前用户是否是会议系统管理员（负责会议室的设备维护、删除、添加、编辑）/或者会议室管理员（负责会议室的申请审核）")
    public Msg updateMeetingRoom(String uid){
        // 是否是会议室管理员
        boolean isMeetingRoomManager = meetingRoomService.isMeetingDormManager(uid);
        String permissionCode = "meeting-system:manager";
        // 是否是会议系统管理员
        boolean isMeetingSystemManager = permissionService.hasAuthorization(uid, permissionCode);
        if (isMeetingRoomManager && isMeetingSystemManager){
            Integer schoolCode = userService.getSchoolCodeByUserId(uid);
            // 当前用户时会议室管理员时，那么需要查询是否有待审核的申请
            List<Integer> applyIds = meetingRoomService.listApplyId(schoolCode, uid);
            boolean hasCheck = false;
            if (applyIds.size() > 0){
                hasCheck = true;
            }
            return Msg.success().add("isMeetingRoomManager", true).add("isMeetingSystemManager", true).add("hasCheck", hasCheck);
        }
        if (isMeetingRoomManager)
            return Msg.success().add("isMeetingRoomManager", true);
        if (isMeetingSystemManager)
            return Msg.success().add("isMeetingSystemManager", true);
        return Msg.fail(ErrorEnum.E_502, ErrorEnum.E_502.getErrorMsg());
    }

    private void sendWeiXinMessage(PubCountEntity pubCountEntity, String content, String schoolName, String weiXinPath){
        String[] paramsWeiXin = {"", schoolName, "系统通知",
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),  content, ""};
        SendUtils.sendByWeixinAndPath(pubCountEntity, paramsWeiXin, pubCountEntity.getTemplateId(), weiXinPath);
    }

    // 短信发给审核进度给会议室申请人
    private void sendToMeetingPerson(String phone, String templateId,String paramString) {
        String[] paramsMobile = new String[2];
        paramsMobile[0] = paramString;
        //适配该通知的短信模板
        paramsMobile[1] = "";
        SendUtils.sendByShortMessage(phone, paramsMobile,templateId);
    }

    private void pushMeetingPersonToDevice(MeetingApplyRecordEntity meetingApplyRecord) {
        //查询出该次会议要推送的设备（即所在会议室的设备）
        List<String> deviceIds = meetingRoomService.listMeetingRoomDevice(meetingApplyRecord);
        if (deviceIds.size() != 0){
            //查询参加这次会议的人员的实义德id用于推送通行权限
            List<String> meetingPersonThdids = meetingRoomService.listMeetingPersonThdid(meetingApplyRecord.getId());
            //设置会议结束时间控制参会人员通行权限
            String meetingDate = new SimpleDateFormat("yyyy-MM-dd").format(meetingApplyRecord.getApplyDate());
            String meetingEndTime = meetingApplyRecord.getEndTime();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String timeString = meetingDate + " " + meetingEndTime + ":00";
            long passEndTime = 0;
            try {
                 passEndTime = simpleDateFormat.parse(timeString).getTime() / 1000;
            } catch (ParseException e) {
                e.printStackTrace();
            }
            //拼接设备id和人员id
            StringBuilder device_ids = new StringBuilder();
            for (String deviceId : deviceIds) {
                device_ids.append(",").append(deviceId);
            }
            String deviceIdStr = device_ids.substring(1);
            StringBuilder personnel_ids = new StringBuilder();
            for (String meetingPersonThdid : meetingPersonThdids) {
                personnel_ids.append(",").append(meetingPersonThdid);
            }
            String personnelIdStr =  personnel_ids.substring(1);

            logger.info("会议室添加参会人员开始");
            Integer schoolCode = userService.getSchoolCodeByUserId(meetingApplyRecord.getApplyUserId());
            SchoolThdidUrlEntity schoolThdidUrl = schoolService.getSchoolThdidUrlAndGroupInfo(schoolCode, Constants.THDID_AI06);
            if (schoolThdidUrl != null){
                ChangePersonTimeThread changePersonTimeThread = new ChangePersonTimeThread(deviceIdStr, personnelIdStr, 1,
                        1, "全体all", 999999, 111111111L,
                        passEndTime, "会议室添加参会人员", 0, schoolThdidUrl.getPathUrl(), schoolThdidUrl.getAccessToken());
                changePersonTimeThread.start();
            }
        }else {
            logger.info("当前会议室没有人脸识别设备不能进行会议签到" + meetingApplyRecord.getMeetingRoomName());
        }
    }
}
